On another thread here in CLF Zbiggy asked about the words ME! ("store in me") and ME@ ("fetch from me"). These words were submitted to the 200x committee for consideration in March 2010 and subsequently retracted.

Zbiggy expressed an interest in using them, and, more specifically, asked if they could be written in standard Forth, without recourse to assembly.

The answer to that question is "I think so!" - certainly, in my hobby system (F83) they are implemented in high level Forth, however they use the word BRANCH which is normally reserved for compiling words such as IF WHILE REPEAT CASE etc.

So, in the spirit of stimulating discussion, I'll present the original code, below. First, some information on the words themselves. I'm re-posting my original RfD post, however, this is *not* an RfD in the context of a submission to Forth 200x. I'm just interested to know if these words can be written in high-level ANS, I'm not proposing to re-submit ME! and ME@ to 200x.

RfD: Proposal for New Forth Words !ME and @ME
=============================================

Revision History
================
23rd March 2010  First Draft

Change Log
==========


Rationale
=========

Problem
-------
A colon definition that needs to maintain state between calls, or
save pertinent associated data cannot do so without the use of
VARIABLEs or VALUEs, which are external to the colon definition.
A better approach is to store related data with the word itself,
promoting encapsulation at the word level.

This proposal presents an alternative data storage solution whereby
the data stored is directly associated with the colon definition
itself, and not reliant on an external VARIABLE or VALUE.

Current Practice
----------------
Current practice is to save stateful information in a variable.
Consider an example whereby in a multi-tasking environment, access
to an IO device shall only be granted to the current task if it is
not already in use by another task:

VARIABLE SerialOwnerID 0 SerialOwnerID !

: CanClaimSerialPort? ( taskid|0  flag )
  ?DUP 0= IF 
    0 SerialOwnerID ! ResetSerialResources EXIT 
  THEN
  SerialOwnerID @ 2DUP 0= -ROT = OR IF
    ( granted )
    DUP SerialOwnerID ! AllocateSerialResources TRUE 
  ELSE 
    ( denied )
    DROP FALSE 
  THEN
;

Here, a variable is used to hold the ID of the task currently using
the serial port. A task wishing to claim the serial port pushes its
task ID onto the stack, and calls CanClaimSerialPort? If the
SerialOwnerID is 0 (not in use) or the same as the requesting task's
ID, the request is granted by pushing TRUE. If any other task
requests the serial port, the request is denied by pushing FALSE.
The serial port can be freed by calling CanClaimSerialPort? with 0
on the stack.

Tyical Use
----------
The above code can be simplified, made more secure, and the
dependence on an external variable removed by the use of the
proposed words !ME and @ME pronounced 'store in me' and 'fetch from
me' respectively.

:!@ CanClaimSerialPort? ( taskid|0  flag )
  ?DUP 0= IF 0 !ME ResetSerialResources EXIT THEN
  @ME 2DUP 0= -ROT = OR IF
    ( granted )
    DUP !ME AllocateSerialResources TRUE 
  ELSE
    ( denied )
    DROP FALSE 
  THEN CR
;

Here, the data is not stored in a variable. Rather, it is stored
'within' the word itself (in practice, the mechanics of how and
where the data is stored and retrieved is implementation specific,
but the Forth programmer can think of/visualise the data as being
stored 'inside' the word). Not only is the dependence on an external
variable removed, but the data can be considered 'protected' since,
unlike variables and values, which are global in scope, the data can
only be accessed by the word that 'contains' it.

It is proposed that any colon definition can use !ME and @ME. Each
colon definition can have exactly one cell sized 'me' storage area.

Remarks
-------
Note that in the above example, the word is built not with : but with
a modified : called :!@ (pronounced "build with storage").
This word is responsible for:

* building the dictionary entry in the normal way, as per :
* reserving a cell of memory;
* initialising the reserved cell to zero;
* making the address of the reserved cell available to the colon
  definition in an implementation specific manner.

Alternative methods are of course available, and indeed welcomed for
discussion. It would probably be preferable if :!@ were not required.
One possible solution would be to place references to !ME and @ME on
the parameter stack or the return stack as they occur, and have ;
back-fill the references, in a similar way to IF...THEN and DO...LOOP
etc. This author welcomes and encourages discussion on this point.

Typical Use
-----------
Use of the above described facility would be desirable for:

* Generating unique IDs;
* Reference counting;
* Holding object instance references;
* Promoting secure/atomic data isolation/security.

Proposal
========
13.6.1.xxxx :!@ LOCAL
---------------------
Interpretation:
Interpretation semantics for this word are undefined.

Compilation:
Compilation semantics for this word are undefined.

Run-time: ( C: "(spaces)name" -- colon-sys )
Create a definition for name as per 6.1.0450, reserve a cell as
storage space, initialising the cell's value to zero. Make the
address of the reserved cell available to the definition being
constructed in an implementation specific manner.



13.6.1.xxxx @ME LOCAL
---------------------
Interpretation:
Interpretation semantics for this word are undefined.

Compilation:
Compilation semantics for this word are undefined.

Run-time: ( -- x )
Fetch the contents of the cell allocated by :!@ and place on
the parameter stack.



13.6.1.xxxx !ME LOCAL
---------------------
Interpretation:
Interpretation semantics for this word are undefined.

Compilation:
Compilation semantics for this word are undefined.

Run-time: ( x -- )
Take the contents of the topmost stack entry and store in the
cell allocated by :!@



Reference Implementation:
=========================
The following reference implementation is written in a Forth-83
style, since this author's knowledge is currently restricted to
Forth-83 type systems.

In the interests of simplicity for example purposes, the
implementation below assumes an ITC system and stores the data
in line with the word, coding a BRANCH instruction to jump over the
data. This example probably constitutes the simplest possible
solution on an ITC system (though rather in-efficient) and can be
coded purely in high level Forth. ANS Forth examples are welcomed.
With carnal knowledge, implementers can of course use much more
sophisticated solutions, reducing size and increasing efficiency.

:!@ FRED 1 2 @ME ;

Is compiled as:

         +----->-----+         +---@ME---+
         |           |         |         |
+----+------+-+----+---+-+---+-+---+---+-+
|FRED|BRANCH|4|DATA|LIT|1|LIT|2|LIT|xxx|@|
+----+------+-+----+---+-+---+-+---+---+-+
                 ^                   |
                 +---------<---------+

It can be seen that @ME has in fact been coded as LIT <address> @
where <address> points to the data cell reserved by :!@

High level code to implement the proposed behaviour is presented
thus:

: :!@ : COMPILE BRANCH 2 CELLS , 0 , ;
: 'ME LATEST @ >CFA 3 CELLS + [COMPILE] LITERAL ;
: @ME ?ME COMPILE @ ; IMMEDIATE
: !ME ?ME COMPILE ! ; IMMEDIATE

Since the above code is possibly not ANS compliant, a discussion of
the code is presented here:

:!@
This word uses : to compile the dictionary entry, and then compiles
a BRANCH <offset> 0 sequence. The idea is that the 0 represents the
reserved storage cell, and the BRANCH simply branches over it.
Note that the requirement for :!@ could be removed by simply
re-defining : thus:
: : : COMPILE BRANCH 2 CELLS , 0 , ;
However, this would mean that a storage cell would be reserved for
every colon definition, regardless of whether !ME or @ME was used
or not. This could be un-desirable on memory constrained systems.


'ME
---
This word calculates the address of the reserved cell by invoking
LATEST to get the dictionary address of the dictionary header just
created by :!@ , converting to a CFA and adding 3 cells to account
for the BRANCH <address> sequence. It then compiles this address
into the current colon definition as a literal. Since address
calculation and compilation is required by both !ME and @ME it is
factored out to become 'ME ('address of me').

@ME
---
Invokes 'ME to compile the address of the reserved cell into the
current definition, and then compiles @ into the definition. Note
this is an immediate word.

!ME
---
Invokes 'ME to compile the address of the reserved cell into the
current definition, and then compiles ! into the definition. Note
this is an immediate word.


Testing
=======

Test of the storage and retrieval of ME data:
---------------------------------------------
:!@ TestME ( Storing: x true -- | Fetching: false -- x )
    IF
      !ME ." Stored " @ME . ." in me."
    ELSE
      ." My value is " @ME .
    THEN
    CR
;

Test storage with:
99 TRUE TestME
Output:
Stored 99 in me
ok

Test retrieval with:
FALSE TestME
Output:
My value is 99
ok

Example UID generator:
----------------------
:!@ GetUID ( -- uid ) @ME 1+ DUP !ME ;

Test with:
GetUID GetUID GetUID GetUID .S
Output:
1 2 3 4 ok

Example Reference Counter:
--------------------------
:!@ RefCount ( true|false - count+1|count-1 )
    @ME SWAP IF 
      1+ 
    ELSE 
      1-
    THEN 
    DUP !ME
;
Test with:
TRUE RefCount TRUE RefCount TRUE RefCount
FALSE RefCount FALSE RefCount FALSE RefCount .S
Output:
1 2 3 2 1 0 ok
